#ifndef __TCPCONNECTION_H__
#define __TCPCONNECTION_H__

#include "EventLoop.h"
#include "InetAddress.h"
#include "Socket.h"
#include "Channel.h"
#include <memory>

using std::shared_ptr;

class Buffer;
class TcpConnection : NonCopyable,
                      public std::enable_shared_from_this<TcpConnection>
{
public:
    typedef shared_ptr<TcpConnection> TcpConnectionPtr;
    typedef function<void(const TcpConnectionPtr &)> ConnectCallback; // 连接建立回调
    typedef function<void(const TcpConnectionPtr &,
                                // const string &)> MessageCallback; // 消息到达回调
                               Buffer *,
                               Timestamp)> MessageCallback;
    typedef function<void(const TcpConnectionPtr &)> CloseCallback; // 连接关闭回调


    TcpConnection(EventLoop *loop, const string &name, int sockfd,
                  const InetAddress &localAddr, const InetAddress &peerAddr);
    ~TcpConnection();
    void setConnectCallback(const ConnectCallback &cb)
    {
        _connectCallback = cb;
    }
    void setMessageCallback(const MessageCallback &cb)
    {
        _messageCallback = cb;
    }
    void setCloseCallback(const CloseCallback &cb)
    {
        _closeCallback = cb;
    }

    void connectEstablished(); // only be called once when TcpServer::newConnection accepts a new connection
    void connectDestroyed();   // only be called once when TcpServer::removeConnection is invoked
    // void send(const string &message);
    // void close();

    string name() const { return _name; }
private:
    enum StateE
    {
        kConnecting,
        kConnected,
        kDisconnected
    };
    void setState(StateE state) { _state = state; }
    void handleRead(); //检查read返回值
    void handleWrite(); 
    void handleClose();
    void handleError();

    EventLoop *_loop;
    const string _name;
    StateE _state;
    unique_ptr<Socket> _socket;
    unique_ptr<Channel> _channel;

    InetAddress _localAddr;
    InetAddress _peerAddr;

    ConnectCallback _connectCallback; // 连接建立回调
    MessageCallback _messageCallback; // 消息到达回调
    CloseCallback _closeCallback; // 连接关闭回调
};

#endif